home *** CD-ROM | disk | FTP | other *** search
- PostScript shared library interface (post.library, with HWGPOST >= V22.26)
- ==========================================================================
-
- HWGPOST, Copyright 1993, 1994 Heinz Wrobel, is mostly calling
- compatible to Post V1.7, Copyright Adrian Aylward 1991, 1992. But it
- is a very different beast inside.
-
- This document is derived from Adrian Aylward's post.library
- documentation. It contains many comments on HWGPOST, developers should
- read, especially those developers who are familiar with the old
- post.library 1.7.
-
-
- Introduction
- ============
-
- The file "post.library" is an AmigaOS Exec shared library containing a
- mostly Level II compliant PostScript interpreter. It is designed to
- be shareable between different processes, supporting arbitrarily many
- PostScript activations - at least until you run out of memory.
-
- This file should be read in conjunction with the header file
- "postlib.h".
-
- The standard user interface source files are distributed with the old
- Post 1.7. Read them as examples for now. If there is different
- information in this document or the current headerfile postlib.h or
- init.ps, the current information holds.
-
-
- Activation Records
- ==================
-
- Simultaneous multiple activations of PostScript are allowed. Before
- using post.library you must first open it by a call to OpenLibrary().
- To create an activation you then call PScreateact() which returns a
- pointer to the activation record. You can then make calls to the
- interpreter library, passing the activation record pointer as an
- argument. You can create several activations, possibly from different
- processes and intermingle the interpreter calls if you wish. But you
- CANNOT PASS ACTIVATION RECORDS BETWEEN PROCESSES! When you have
- finished with an activation, call PSdeleteact() to delete it and free
- the memory it used. Do not free bitmap memory or filehandles before
- freeing the activation record! When you have finished with the library
- call CloseLibrary(); if no other processes have it open, then Exec can
- remove it from memory if the space is needed.
-
- N.B. the library can only be called from a process, as it calls
- various AmigaDOS functions. IT IS NOT PERMISSIBLE TO PASS ACTIVATION
- RECORDS BETWEEN PROCESSES! NOTE THIS WELL!
-
-
- The Parameter Block
- ===================
-
- The parameter block is the argument to PScreateact(). It specifies
- the addresses of the bitmap planes, size of the page, and the amount
- of memory to be allocated for the activation etc ... Its format is
- defined in detail in the header file postlib.h.
-
- N.B. all ints are 32 bits, shorts are 16 bits.
-
- The page size is limited to 30000 pixels a side. The densities
- (pixels per inch) may be any strictly positive integer value. The y
- direction may be set to +1 - if the bitmap rows are in PostScript
- order (bottom row first) or -1 - Amiga order (top row first).
-
- page.buf[24] Bitplane pointers, up to 24
- page.len Size in bytes of each plane
- page.depth Number plane pointers to use
- page.flags Special device options
- page.bitspercolor How many plane pointers to be used per gun.
- page.PSextdevice An optional extension to the device information
- page.xbytes Number of bytes in each row
- page.xsize Number of pixels in each row
- page.ysize Number of rows
- page.ybase Base of current band
- page.yheight Total height of full page, for band rendering
- page.xden X density
- page.yden Y density
- page.ydir Y direction
-
- To specify how many bitplanes are used per color, you set
- "bitspercolor" to the appropriate value. If this value is not set, one
- bitplane per color is assumed and only 1, 3, and 4 are permissible as
- depth in this case. Example: RGB 3:3:2 => depth=8, bitspercolor=3.
-
- Note that bitspercolor should not exceed 8.
-
- For special use, the page device description can be enhanced by
- setting page.PSextdevice. The PSextdevice structure contains the
- following fields.
-
- flags Extension of the main flags field.
-
- maskbuf If set, must be a plane as in page.buf. For
- any rendering you'll get bits set in this mask
- plane. This gives you a mask of the actually
- used places in the buffer. The mask might be
- useful for BltMaskBitMapRastPort() or some
- such. erasepage will clear this mask plane.
-
- Kbuf[8] Eight additional plane pointers to allow for
- true eight bit CMYK rendering. You need to set
- the depth to a value greater 24 for these to
- be used.
-
- The length of these structures is subject to change. Always set unused
- fields to zero.
-
- As a starting point for memory sizes try the values following. (These
- are defined in the header file.) For normal PostScript programs the
- defaults are perfectly satisfactory. If you specify a value of zero
- the default will be used instead; values less than the minimum will be
- increased.
-
- memvlen 50000 VM
- memflen 60000 Font cache
- memllen 15000 Path lines
- memhlen 20000 Halftones
- memplen 60000 Pattern cache
-
- The user data pointer is intended to be used to identify multiple
- activations. You can set it to any value you like. The function
- pointers are described below.
-
- userdata User data pointer
- flushfunc Flush page function pointer
- copyfunc Copy page function pointer
-
- The standard input and output streams are the AmigaDOS file handles to
- be used by the interpreter for %stdin, %stdout, %stderr. Also the
- standard output is used for prompts and the error output for error
- messages. These file handles will not be closed by the interpreter
- even though PostScript file objects referring to them may be closed.
- You should not set them to NULL. If you don't need any input or
- output, set up valid NIL: filehandles!
-
- infh Standard Input file handle
- outfh Standard Output file handle
- errfh Standard Error file handle
-
- These are for backwards compatibility with the infamous "callextfunc"
- operator. You'll find details below.
-
- funcmax Number of external functions
- functab Pointer to external function table, or zero
-
- Anything else in the block is reserved and must be set to zero.
-
-
- Notes on the special device flags
- ---------------------------------
-
- In the header file "postlib.h" you will find some flag definitions for
- the main flag field of the parameter page. They need more explanation.
-
- HWGPOST_DEVx_NOSHADE
-
- Halftoning is in effect suppressed. No halftone screens will
- be used. Any color intensity that would cause shading will be
- rendered as the next lower color value truly representable
- within the bitplanes would. Shading is simply turned off.
-
- HWGPOST_DEVx_CMYK
-
- Old post.library supported the CMYK color space and operators.
- When converting any colors to values passed to the transfer
- functions, it creates RGBW values, though, instead of CMYK.
- With this flag set, the colorspace mapping algorithm will stay
- with CMYK and CMYK will be passed to the transfer functions if
- applicable.
-
- HWGPOST_DEVx_INVERTOUTPUT
-
- The output of the transfer functions represent the value that
- should be rendered into the bitplanes. With this flag set,
- these values in the range [0.0;1.0] will effectively reversed
- with a simple "shade = 1.0 - shade" before the rendering is
- set up. This is the easiest way to create "negative" output
- and might come in handy for multiple bitplane color handling,
- where black should be "all bits 0" instead of "all bits 1" in
- the planes. This is good for true color rendering.
-
-
- Function Pointers
- =================
-
- There are two function pointers within the parameter block, which are
- used when the interpreter needs to call routines supplied by its
- client. If the pointers are zero, the calls are skipped.
-
- To help identify calls from multiple activations, the activation
- record address is also passed in A0 and the userdata pointer in A1.
-
- flushfunc(D0: int y1, D1: int y2)
-
- Flush the bitmap to the screen. The interpreter calls this function
- after a painting operation has updated the bitmap. Then if the output
- is being viewed interactively the client can update the screen or
- window. The arguments are the range of bitmap rows (y1 ... y2-1) that
- may have been updated.
-
- copyfunc(D0: int num)
-
- Copy the page to the output device. The argument is the value of
- "#copies", which should be taken into account if the output is to a
- printer, but is not meaningful for screen output. You shoud take a
- look at the description for PSsignalint() below, too.
-
-
- Calling External Functions
- ==========================
-
- The original "callextfunc" operator of post.library <= V1.7 is no
- longer supported even though it is still available in disguise as
- "@callextfunc". Use of this operator is strongly discouraged as it
- might lure you into making assumptions about internal HWGPOST data
- representations.
-
- A more general way to call external functions has been devised via the
- new "@calluserhook" operator. This operator collects the arguments,
- passes them to a "Hook" as defined by the utility.library, records any
- changes and returns the result. This is the calling sequence:
-
- mark <args..> <userhookadr> <msgadr> @calluserhook
-
- On return the operand stack will look like this:
-
- mark <args..> <resint>
-
- A number from zero to eight arguments is supported. Only certain
- PostScript objects may be passed as arguments: integers, reals, and
- booleans are passed as the 32 bit bitpatterns corresponding to their
- values; strings are passed as the 32 bit address of their contents
- with the length as the following 32 bit integer. (N.B. PostScript
- strings are terminated by length; there is no terminating null unless
- the program puts one there. The user function may not go beyond the
- string length!)
-
- <hookadr> and <msgadr> are integers that are used as 32 bit memory
- address. If no <msgadr> is needed, just use 0. These addresses should
- be passed to the interpreter via the PSintstring() function in full
- PostScript notation like "/hookadr 16#780ab44 def" to be used by
- special PostScript code. It is advisable to put them into special,
- private dictionaries.
-
- The argument values passed are put into an array of 32 bit values
- which is passed as "objectptr" to the Hook. The return value will be
- put on the operand stack as <resint> and any changes to numeric values
- in the 32 bit array will be put back into the args on the operand
- stack. The Hook may change string contents within the address and
- length passed to it.
-
- As an example assume this calling sequence:
-
- mark 1 string1 2.5 4 string2 false hookadr 0 @calluserhook
-
- The 32 bit array passed to the hook as object will have these
- contents:
-
- array[0]: 32 int 1
- array[1]: string1: address
- array[2]: string1: length
- array[3]: IEEE float 2.5
- array[4]: 32 int 4
- array[5]: string2: address
- array[6]: string2: length
- array[7]: 0
-
- If the hook function changes array[0] to 3, array[7] to 1, and returns
- -1, the resulting operand stack will contain these values:
-
- mark 3 string1 2.5 4 string2 true -1
-
- Changing a string address or length should not be tried. If results
- are not needed, a cleartomark will get rid of them easily.
-
- There should not be any assumptions made about internal representation
- of objects. For booleans, only 0 and 1 should be used.
-
- N.B. PSintstring() is not guaranteed to work recursively. So calling
- it from the hook is not a good idea. The Hook is called on the
- interpreters context. If a local near data section is needed, the Hook
- function is responsible for setting up A4, e.g. from hook->h_Data.
- Standard rules for saving registers apply. Do not assume that A4
- contains anything useful!
-
-
- Calling External Functions with @callextfunc
- ============================================
-
- The original "callextfunc" operator of post.library <= V1.7 is no
- longer supported even though it is still available in disguise as
- "@callextfunc". Use of this operator is strongly discouraged as it
- might lure you into making assumptions about internal HWGPOST data
- representations. It is only here for limited backwards compatibility.
- Do not use it for new SW!
-
- If you supply an external function table your PostScript program can
- call the functions within it by the "@callextfunc" operator. The
- contents of the table are the addresses of the function entry points.
- The functions must have standard (Lattice, non-registerised) C
- compatible calling sequences. They must not assume any useful value in
- register A4 on entry, and must preserve A4 and the other C registers
- on exit.
-
- Unlike with post.library <= 1.7 there is additional information given,
- though. To help identify calls from multiple activations, the activation
- record address is also passed in A0 and the userdata pointer in A1.
-
- Only certain PostScript objects may be passed as arguments: integers
- reals and booleans are passed as the 32 bit bitpatterns corresponding
- to their values; arrays and strings are passed as the 32 bit address
- of their contents - if the length is required it must be passed
- separately. (N.B. PostScript strings are terminated by length; there
- is no terminating null unless the program puts one there.)
-
- It is theoretically possible to pass arbitrary objects by including
- them within an array, but then you would need to know their PostScript
- representation. As the representation has been changed thoroughly for
- HWGPOST and will continue to change in the future, this "feature" is
- of no use at all!
-
- The "@callextfunc" operator is only inserted into the system
- dictionary if a function table is present. So you will not find it if
- you attempt to execute it from the standard user interface.
-
-
- Library Entry points
- ====================
-
- Prototypes and pragmas for the entry points are defined in the header
- file.
-
-
- Create a PostScript activation
- ------------------------------
-
- D0:int arec = PScreateact(A1:struct PSparm *parm)
-
- The result is the address of the new activation record. If the
- activation fails an error code is returned instead - zero if the
- interpreter failed to start at all because there was insufficient free
- memory, or an interpreter error code if there was an error during
- initialisation. Otherwise the result is the address of the activation
- record. The result is always returned as an int. If is is greater
- than errmax then the activation was successful, and the value is an
- address; otherwise the activation failed, and the result is zero or an
- error code.
-
-
- Delete a PostScript activation
- ------------------------------
-
- VOID PSdeleteact(A0:APTR arec)
-
- The activation record is deleted and the associated memory is freed.
-
-
- Interpret a string or file
- --------------------------
-
- D0:int errnum = PSintstring(A0:APTR arec, A1:char *string,
- D0:int length, D1:int flags)
-
-
- Flag bits:
-
- PSFLAGSTRING, PSFLAGGFILE
-
- If PSFLAGSTRING is set, the contents of the string are
- interpreted as PostScript source. If the flag PSFLAGFILE is
- set, the string is a file name. Then the file's contents are
- interpreted. If neither of these flag bits are set the string
- is ignored, but the other flag bits still have their effects;
- if both are set the result is undefined.
-
-
- PSFLAGINTER
-
- If PSFLAGINTER is set (when interpreting a file), the file is
- considered to be interactive. The banner is printed, and the
- interpreter prompts for each line of input from the file.
-
-
- PSFLAGCLEAR
-
- If PSFLAGCLEAR is set, then after interpretation the operand
- stack is cleared and the dictionary stack is popped until only
- the system and user dictionaries remain. The execution stack
- is emptied, too.
-
-
- PSFLAGSAVE
-
- If PSFLAGSAVE is set, job server behaviour is set up for the
- current job only. It is functionally equivalent to
- (PSFLAGSTARTJOBSERVER| PSFLAGENDJOBSERVER) but you shouldn't
- use the job server flags instead if you really want
- PSFLAGSAVE.
-
- IMPORTANT: For running setup files like "init.ps", you should
- not use PSFLAGSAVE or job server flags!
-
-
-
- PSFLAGSTARTJOBSERVER, PSFLAGENDJOBSERVER
-
- With PSFLAGSTARTJOBSERVER and PSFLAGENDJOBSERVER one can
- create one job server run, spanning multiple invocations of
- PSintstring(). The former forces a successful startjob with a
- "false" operand before running the job, the latter forces a
- successful startjob with a "true" operand after running the
- job and clears out the execution stack and does some other
- private things. These flags do not nest. If you think about
- using them in a tricky way: Think again and ask _first_.
-
- IMPORTANT: For running setup files like "init.ps", you should
- not use PSFLAGSAVE or job server flags!
-
-
- PSFLAGERASE
-
- If PSFLAGERASE is set, then the page is erased. This happens
- right at the end, after any vm restore, so the page is erased
- taking into account the restored transfer function(s).
-
-
- This routine is NOT guaranteed to recurse correctly; strange things or
- crashes may happen if you try to call it from an external function
- called from the same activation.
-
-
- Signal an interrupt
- -------------------
-
- VOID PSsignalint(A0:APTR arec, D0:int flag)
-
- This routine may be called to set an interrupt signal flag to notify
- the interpreter of a special condition. The possible flag values are
- defined in the header file postlib.h. You may or multiple bit flags
- together. The interpreter tests these flags at the head of its main
- loop, and also within certain potentially length operators (=, ==,
- stack and pstack). If a flag is set it the interpreter will take
- appropriate action immediately and automatically clear the
- corresponding flag bit. You may safely call this routine at any time
- during the life of the activation. It is intended to be called from
- within your task's exception handler, if the CTRL-C break signal is
- set. Unlike with post.library <= V1.7 it is not possible to clear a
- flag once it has been set by calling this function. Only the
- interpreter will clear a flag bit when it is handled.
-
- You may also call this function from the copypage callback with the
- PSINTSIGF_KILL flag. This will make the interpreter skip the erasepage
- command when doing a showpage, and allows you to obtain a generated
- bitmap easily. You don't need a backup bitmap then. It is advisable of
- course not to use PSFLAGERASE either in this case.
-
-
- Signal a floating point error
- -----------------------------
-
- VOID PSsignalfpe(A0:APTR arec)
-
- This routine is intended to be called whenever a floating point trap
- is generated by the interpreter. It generates an immediate
- undefinedresult error. You must not call it at any other time; if you
- do you will crash the machine. It is only useful if you are using the
- version of the library compiled for the 68881 FPU or compatible chips.
- (The software floating point routines do not generate traps). Before
- calling the library you should set up a trap handler and set the bits
- in the fpcr register to enable the traps. (If you do not set up the
- traps, the FPU will substitute the special value not-a-number for the
- result and continue. The undefinedresult error will not be triggered,
- and results of your program may be incorrect.) If you application
- does not use the FPU you can simply direct all traps to the library,
- otherwise it is essential that you ensure that you only call this
- routine if the trap derived from the library and not your own code.
-
-
- Error
- -----
-
- VOID PSerror(A0:APTR arec, D0:int errnum)
-
- This routine is intended to be called from within your own flush or
- copy page functions, to signal that an error ocurred. You can also
- call it from an external function. You must not call it at any other
- time; if you do, you will crash the machine. It calls the PostScript
- error handler and never returns. The values for the error number are
- defined in the header file.
-
-
- Return a text string corresponding to an error name
- ---------------------------------------------------
-
- D0:const char *str = PSerrstr(A0:int arec, D0:int errnum)
-
- Converts a postscript error number to a text string. Returns NULL if
- the number is out of range.
-
-
- Change device page
- ------------------
-
- VOID PSsetdevice(A0:APTR arec, A1:struct PSdevice *page)
-
- Note: While "setpagedevice" is not currently available, the effects
- caused by PSsetdevice() are _very_ likely to change in many ways
- when the time comes. If you feel that you rely on effects other
- than simply replacing the device page buffer and dimensions,
- CONTACT ME NOW.
-
- Changes the device page buffer and dimensions. If the clip path is
- still set to its initial value (the whole page) it is changed to match
- the new page size; otherwise it is unchanged (and may therefore
- possibly exceed the new page size). All the clip paths saved on the
- graphics stack are similarly changed. The CTM at the topmost saved
- graphics state (the one returned to by a "grestoreall" when there are
- no active VM saves) is reset to match the new page size and density.
- Otherwise the CTM is not affected; you will likely want to execute
- "initmatrix" afterwards.
-
- The interactions of this routine with the stack of saved graphics
- states are complex, leading to unexpected behaviour unless you
- understand exactly what is happening. So it is safest to think twice
- about calling it and always call it when there are no save's or
- gsave's active, and then to reinitialise the CTM immediately.
- In other words: You better not use it.
-
- This routine should not be called from within a character build,
- kerning, or imaging procedure.
-
-
- Problems, Comments, and Bugs
- ============================
-
- You will find my complete address in the header file "postlib.h".
- Contact me if you have any questions or suggestions. Don't rely on
- empirical programming. It is a lot faster and easier to ask than
- wasting time with fiddling around.
-
- Heinz Wrobel
- <heinz@hwg.muc.de>
-
- *** EOT ***
-